// Package object 用于将Map结构体封装为一个支持并发安全的泛型的键值对存储器
package object

import (
	"bytes"        // 引入bytes包，用于操作字节
	"encoding/gob" // 引入gob包，用于对象的编码和解码
	"errors"       // 引入errors包，用于生成错误信息
	"reflect"      // 引入reflect包，用于类型检查
	"sync"         // 引入sync包，用于同步操作，提供锁等同步工具
)

// mapLocker 接口定义了锁操作的方法
type mapLocker interface {
	Lock()    // 加锁
	Unlock()  // 解锁
	RLock()   // 读锁
	RUnlock() // 读解锁
}

// mapNotLocker 结构体实现mapLocker接口，但方法为空实现，即不实际进行加锁操作
type mapNotLocker struct{}

func (mapNotLocker) Lock()    {} // 加锁，不执行任何操作
func (mapNotLocker) Unlock()  {} // 解锁，不执行任何操作
func (mapNotLocker) RLock()   {} // 读锁，不执行任何操作
func (mapNotLocker) RUnlock() {} // 读解锁，不执行任何操作

// mapSafeLocker 结构体提供了实际的锁操作
type mapSafeLocker struct {
	locker sync.RWMutex // 使用读写互斥锁
}

func (l *mapSafeLocker) Lock()    { l.locker.Lock() }    // 加锁
func (l *mapSafeLocker) Unlock()  { l.locker.Unlock() }  // 解锁
func (l *mapSafeLocker) RLock()   { l.locker.RLock() }   // 读锁
func (l *mapSafeLocker) RUnlock() { l.locker.RUnlock() } // 读解锁

// Map 是一个泛型映射，提供键值对的存储，以及并发控制
type Map[K comparable, V any] struct {
	Value  map[K]V   // 存储实际的键值对
	locker mapLocker // 控制并发访问的锁
}

// NewMap 创建一个新的Map实例，根据threadSafe参数决定是否线程安全
func NewMap[K comparable, V any](threadSafe bool) *Map[K, V] {
	m := &Map[K, V]{
		Value: make(map[K]V), // 初始化键值对存储
	}
	if threadSafe {
		m.locker = &mapSafeLocker{} // 线程安全，使用有实际加锁行为的锁
	} else {
		m.locker = &mapNotLocker{} // 非线程安全，使用空操作的锁
	}
	return m
}

// Add 方法添加一个键值对，如果键已存在，返回false
func (m *Map[K, V]) Add(key K, value V) bool {
	m.locker.Lock()         // 加锁
	defer m.locker.Unlock() // 延迟解锁
	if _, ok := m.Value[key]; ok {
		return false // 如果键已存在，不添加，返回false
	}
	m.Value[key] = value // 添加键值对
	return true
}

// Update 方法更新一个键对应的值，如果键不存在，返回false
func (m *Map[K, V]) Update(key K, value V) bool {
	m.locker.Lock()         // 加锁
	defer m.locker.Unlock() // 延迟解锁
	if _, ok := m.Value[key]; !ok {
		return false // 如果键不存在，不更新，返回false
	}
	m.Value[key] = value // 更新值
	return true
}

// Set 方法设置一个键对应的值，如果键不存在则新建，如果存在则更新
func (m *Map[K, V]) Set(key K, value V) {
	m.locker.Lock()         // 加锁
	defer m.locker.Unlock() // 延迟解锁
	m.Value[key] = value    // 更新值
}

// Get 方法获取一个键对应的值
func (m *Map[K, V]) Get(key K) (V, bool) {
	m.locker.RLock()          // 读锁
	defer m.locker.RUnlock()  // 延迟读解锁
	value, ok := m.Value[key] // 获取键对应的值
	return value, ok          // 返回键对应的值
}

// Delete 方法删除一个键值对，如果键不存在，返回false
func (m *Map[K, V]) Delete(key K) bool {
	m.locker.Lock()         // 加锁
	defer m.locker.Unlock() // 延迟解锁
	if _, ok := m.Value[key]; !ok {
		return false // 如果键不存在，不删除，返回false
	}
	delete(m.Value, key) // 删除键值对
	return true
}

// Clean 方法清空Map中所有键值对
func (m *Map[K, V]) Clean() {
	m.locker.Lock()         // 加锁
	defer m.locker.Unlock() // 延迟解锁
	m.Value = make(map[K]V) // 重新初始化map，清空键值对
}

// ForEach 方法遍历Map，对每个键值对执行callback函数
func (m *Map[K, V]) ForEach(callback func(key K, value V)) {
	m.locker.RLock()         // 读锁
	defer m.locker.RUnlock() // 延迟读解锁
	for k, v := range m.Value {
		callback(k, v) // 执行回调函数
	}
}

// Size 方法返回Map中键值对的数量
func (m *Map[K, V]) Size() int {
	m.locker.RLock()         // 读锁
	defer m.locker.RUnlock() // 延迟读解锁
	return len(m.Value)      // 返回键值对数量
}

// Keys 方法返回Map中所有的键
func (m *Map[K, V]) Keys() []K {
	m.locker.RLock()                // 读锁
	defer m.locker.RUnlock()        // 延迟读解锁
	keys := make([]K, len(m.Value)) // 初始化键切片
	i := 0
	for k := range m.Value {
		keys[i] = k // 将键添加到切片中
		i++
	}
	return keys // 返回键切片
}

// Values 方法返回Map中所有的值
func (m *Map[K, V]) Values() []V {
	m.locker.RLock()                  // 读锁
	defer m.locker.RUnlock()          // 延迟读解锁
	values := make([]V, len(m.Value)) // 初始化值切片
	i := 0
	for _, v := range m.Value {
		values[i] = v // 将值添加到切片中
		i++
	}
	return values // 返回值切片
}

// Contains 方法检查Map中是否含有指定的键
func (m *Map[K, V]) Contains(key K) bool {
	m.locker.RLock()         // 读锁
	defer m.locker.RUnlock() // 延迟读解锁
	_, ok := m.Value[key]    // 检查键是否存在
	return ok                // 返回检查结果
}

// IsEmpty 方法检查Map是否为空
func (m *Map[K, V]) IsEmpty() bool {
	m.locker.RLock()         // 读锁
	defer m.locker.RUnlock() // 延迟读解锁
	return len(m.Value) == 0 // 如果键值对数量为0，则为空
}

// Clone 方法克隆一个Map，可选择是否线程安全
func (m *Map[K, V]) Clone(threadSafe bool) (*Map[K, V], error) {
	m.locker.Lock()                   // 加锁
	defer m.locker.Unlock()           // 延迟解锁
	buffer := new(bytes.Buffer)       // 创建一个新的bytes.Buffer
	encoder := gob.NewEncoder(buffer) // 创建一个新的编码器
	if err := encoder.Encode(m.Value); err != nil {
		return nil, errors.New("编码错误，存在复杂的数据结构，无法深度拷贝。") // 如果编码失败，返回错误
	}
	var dst map[K]V                   // 创建一个新的map
	decoder := gob.NewDecoder(buffer) // 创建一个新的解码器
	if err := decoder.Decode(&dst); err != nil {
		return nil, errors.New("解码错误，存在复杂的数据结构，无法深度拷贝。") // 如果解码失败，返回错误
	}
	result := NewMap[K, V](threadSafe) // 创建一个新的Map实例
	result.Value = dst                 // 设置克隆后的值
	return result, nil                 // 返回新的Map实例和nil
}

// Merge 方法合并另一个Map到当前Map中，keepOldValue决定是否保留旧值
func (m *Map[K, V]) Merge(m2 *Map[K, V], keepOldValue bool) {
	m.locker.Lock()         // 加锁
	defer m.locker.Unlock() // 延迟解锁
	if keepOldValue {
		for k, v := range m2.Value {
			if _, ok := m.Value[k]; ok {
				continue // 如果keepOldValue为true且键已存在，保留原值，不覆盖
			}
			m.Value[k] = v // 如果键不存在，添加键值对
		}
		return // 返回
	}
	for k, v := range m2.Value {
		m.Value[k] = v // 否则，直接覆盖键值对
	}
}

// Entries 方法返回Map中所有的键值对
func (m *Map[K, V]) Entries() map[K]V {
	m.locker.RLock()         // 读锁
	defer m.locker.RUnlock() // 延迟读解锁
	result := make(map[K]V)  // 创建新的map
	for k, v := range m.Value {
		result[k] = v // 拷贝键值对到新map
	}
	return result // 返回新map
}

// Equals 方法判断两个Map是否相等
func (m *Map[K, V]) Equals(m2 *Map[K, V]) (bool, error) {
	srcMap, err := m.Clone(false) // 克隆当前Map
	if err != nil {
		return false, errors.New("存在复杂的数据结构，无法比较。") // 如果克隆失败，返回错误
	}
	dstMap, err := m2.Clone(false) // 克隆参数Map
	if err != nil {
		return false, errors.New("存在复杂的数据结构，无法比较。") // 如果克隆失败，返回错误
	}
	if len(srcMap.Value) != len(dstMap.Value) {
		return false, nil // 如果两个Map的长度不一致，返回不相等
	}
	for k, v := range srcMap.Value {
		if v2, ok := dstMap.Value[k]; !ok || !reflect.DeepEqual(v, v2) {
			return false, nil // 如果有键不存在或值不相等，返回不相等
		}
	}
	return true, nil // 否则返回相等
}
